#include "stdafx.h"
#include <boost/test/auto_unit_test.hpp>
#include "bmock.hpp"
#include "detail/bmock_func_info.hpp"

bool EqualArgs(const std::vector<std::string>& v1, const std::vector<std::string>& v2)
{
	if (v1.size() != v2.size()) 
		return false;

	for (size_t i = 0; i < v1.size(); i++)
	{
		if (v1[i] != v2[i])
			return false;
	}

	return true;
}

struct test_func_info: public bmock::func_info{
	test_func_info(std::string funcSig, std::string funcName):
	func_info(funcSig, funcName)
	{}

	std::string getFuncName()
	{
		return funcName_;
	}
	
	std::string getReturnType() {
		return returnType_;
	}

	std::vector<std::string> getArgsTypes() {
		return argTypes_;
	}
};

struct func_test_{
};

BMOCK_TEST(func_test_,test_simple_function_no_args){
	test_func_info test_("void f()", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_simple_function_no_args_void_in_brackets) {
	test_func_info test_("void f(void)", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_with_pointers) {
	test_func_info test_("void f(char**)", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("char**");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_with_ref) {
	test_func_info test_("void f(int&)", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("int&");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_with_array) {
	test_func_info test_("void f(char[])", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("char[]");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_with_qualifiers) {
	test_func_info test_("void f(const char* const)", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("const char* const");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_all) {
	test_func_info test_("void f(volatile char)", "f");
	std::string expectedRetType = "void";
	std::string expectedFuncName = "f";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("volatile char");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}


BMOCK_TEST(func_test_,test_argument_list_mult_args) {
	test_func_info test_("void * f2(int *, char &, const std::string)", "f2");
	std::string expectedRetType = "void *";
	std::string expectedFuncName = "f2";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("int *");
	expectedArgTypes.push_back("char &");
	expectedArgTypes.push_back("const std::string");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());	
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_list_mult_args_struct) {
	test_func_info test_("void * f2(int *, char &, struct A)", "f2");
	std::string expectedRetType = "void *";
	std::string expectedFuncName = "f2";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("int *");
	expectedArgTypes.push_back("char &");
	expectedArgTypes.push_back("struct A");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_list_mult_args_template) {
	test_func_info test_("void * f2(int *, std::pair<std::string, int> &, struct A)", "f2");
	std::string expectedRetType = "void *";
	std::string expectedFuncName = "f2";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("int *");
	expectedArgTypes.push_back("std::pair<std::string, int> &");
	expectedArgTypes.push_back("struct A");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

BMOCK_TEST(func_test_,test_argument_list_mult_args_template_in_return_type) {
	test_func_info test_("std::vector<std::list<struct BCD> > f2(int *, std::pair<std::string, int> &, struct ABC)", "f2");
	std::string expectedRetType = "std::vector<std::list<struct BCD> >";
	std::string expectedFuncName = "f2";
	std::vector<std::string> expectedArgTypes;
	expectedArgTypes.push_back("int *");
	expectedArgTypes.push_back("std::pair<std::string, int> &");
	expectedArgTypes.push_back("struct ABC");

	BOOST_CHECK_EQUAL(expectedRetType, test_.getReturnType());
	BOOST_CHECK_EQUAL(expectedFuncName, test_.getFuncName());
	BOOST_CHECK(EqualArgs(expectedArgTypes, test_.getArgsTypes()));
}

